package com.ala4.oxcafe.service.impl;

import com.ala4.oxcafe.boot.manager.UserTokenManager;
import com.ala4.oxcafe.boot.page.PageDomain;
import com.ala4.oxcafe.common.utils.collection.CollUtil;
import com.ala4.oxcafe.common.utils.object.ObjectUtil;
import com.ala4.oxcafe.constants.OrderNoConstant;
import com.ala4.oxcafe.dto.OperateDTO;
import com.ala4.oxcafe.entity.RoleInfo;
import com.ala4.oxcafe.entity.StoreInfo;
import com.ala4.oxcafe.entity.UserInfo;
import com.ala4.oxcafe.enums.OperateEnum;
import com.ala4.oxcafe.exception.BusinessException;
import com.ala4.oxcafe.repository.RoleInfoRepository;
import com.ala4.oxcafe.repository.StoreInfoRepository;
import com.ala4.oxcafe.repository.UserInfoRepository;
import com.ala4.oxcafe.repository.UserRoleRelRepository;
import com.ala4.oxcafe.service.StoreInfoService;
import com.ala4.oxcafe.utils.CodeGenUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author PING
 * @version 1.0.0
 * @date 2025/8/14 15:08
 */
@Slf4j
@Service
@AllArgsConstructor
public class StoreInfoServiceImpl implements StoreInfoService {

    private final StoreInfoRepository storeInfoRepository;

    private final UserInfoRepository userInfoRepository;

    private final UserTokenManager userTokenManager;
    private final RoleInfoRepository roleInfoRepository;
    private final UserRoleRelRepository userRoleRelRepository;

    @Override
    public IPage<StoreInfo> storeInfoPage(PageDomain pageDomain, StoreInfo storeInfo) {
        return storeInfoRepository.selectStoreInfoPage(pageDomain, storeInfo);
    }

    @Override
    public List<StoreInfo> storeInfoList(StoreInfo storeInfo) {
        return storeInfoRepository.selectStoreInfoList(storeInfo);
    }

    @Override
    public StoreInfo createStoreInfo(StoreInfo storeInfo) {

        List<StoreInfo> storeInfoList = storeInfoRepository.list(Wrappers.<StoreInfo>lambdaQuery().eq(StoreInfo::getStoreCode, storeInfo.getStoreCode()));

        if (CollUtil.isNotEmpty(storeInfoList)) {
            throw new BusinessException("门店编码[{}]已存在", storeInfo.getStoreCode());
        }
        storeInfo.setStoreCode(CodeGenUtil.getDateFormatCode(OrderNoConstant.STORE_CODE));
        // 保存门店信息
        storeInfoRepository.save(storeInfo);

        // 创建门店顺带去创建一个用户
        this.createStoreUserInfo(storeInfo);

        return storeInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public StoreInfo updateStoreInfo(StoreInfo storeInfo) {
        // 这里先查询一次数据库的数据
        StoreInfo dbStoreInfo = this.storeInfoInfo(storeInfo.getId());

        // 更新门店信息
        storeInfoRepository.updateByIdOptimistic(storeInfo);

        // 说明修改了门店手机号 需要去修改用户的信息
        this.storeUpdateUserInfoPhone(dbStoreInfo.getContactPhone(), storeInfo);

        // 如果门店状态不一致 说明修改了门店状态 并且是 修改成冻结 需要去进行冻结操作
        if (!dbStoreInfo.getStatus().equals(storeInfo.getStatus())) {
            OperateDTO operateDTO = new OperateDTO();
            operateDTO.setId(storeInfo.getId());
            operateDTO.setOperate(storeInfo.getStatus() == 1 ? OperateEnum.FREEZE : OperateEnum.THAW);
            // 这里需要去操作冻结
            return this.freezeThaw(operateDTO);
        }

        return storeInfo;
    }

    /**
     * 修改用户手机号
     *
     * @param olePhone 旧手机号
     * @param storeInfo 门店信息
     */
    private void storeUpdateUserInfoPhone(String olePhone, StoreInfo storeInfo) {
        // 新手机号
        String newPhone = storeInfo.getContactPhone();

        // 旧手机号和新手机号是否相同
        if (!olePhone.equals(newPhone)) {
            // 判断新手机号是否可用
            UserInfo newUserInfo = userInfoRepository.getOne(Wrappers.<UserInfo>lambdaQuery().eq(UserInfo::getPhoneNumber, newPhone));
            if (ObjectUtil.isNotNull(newUserInfo)) {
                throw new BusinessException("手机号[{}]已绑定用户[{}],无法修改", newPhone, newUserInfo.getNickName());
            }
        }
        UserInfo userInfo = userInfoRepository.getOne(Wrappers.<UserInfo>lambdaQuery().eq(UserInfo::getPhoneNumber, olePhone));

        // 这里直接更新账号的手机号和昵称
        if (ObjectUtil.isNotNull(userInfo)) {
            userInfo.setPhoneNumber(newPhone);
            userInfo.setNickName(storeInfo.getStoreName());
            userInfoRepository.updateById(userInfo);
        }
    }

    @Override
    public void deleteStoreInfo(Long storeId) {
        StoreInfo storeInfo = this.storeInfoInfo(storeId);

        storeInfoRepository.removeById(storeInfo.getId());
    }

    @Override
    public StoreInfo storeInfoInfo(Long storeId) {
        StoreInfo storeInfo = storeInfoRepository.getById(storeId);
        if (ObjectUtil.isNull(storeInfo)) {
            throw new BusinessException("门店信息不存在");
        }
        return storeInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public StoreInfo freezeThaw(OperateDTO operateDTO) {

        StoreInfo storeInfo = this.storeInfoInfo(operateDTO.getId());

        switch (operateDTO.getOperate()) {
            case THAW -> storeInfo.setStatus(0);
            case FREEZE -> storeInfo.setStatus(1);
            default -> throw new BusinessException("未知的操作");
        }
        storeInfoRepository.updateByIdOptimistic(storeInfo);

        // 需要去更新门店用户的启用和禁用
        this.updateStoreUserStatus(storeInfo);

        return storeInfo;
    }

    /**
     * 更新门店用户的状态
     *
     * @param storeInfo 门店信息
     */
    private void updateStoreUserStatus(StoreInfo storeInfo) {
        // 查找门店的用户
        List<UserInfo> storeUserList = userInfoRepository.list(Wrappers.<UserInfo>lambdaQuery().eq(UserInfo::getStoreId, storeInfo.getId()));
        if (CollUtil.isNotEmpty(storeUserList)) {
            for (UserInfo userInfo : storeUserList) {
                userInfo.setStatus(storeInfo.getStatus());
                // 如果是禁用 那么需要强制下线在线的用户
                if (storeInfo.getStatus() == 1) {
                    userTokenManager.offlineUser(userInfo.getId());
                }
            }
            // 更新用户
            userInfoRepository.updateBatchById(storeUserList);
        }
    }

    /**
     * 创建门店用户
     *
     * @param storeInfo 门店信息
     */
    private void createStoreUserInfo(StoreInfo storeInfo) {
        UserInfo userInfo = new UserInfo();

        userInfo.setNickName(storeInfo.getStoreName());
        userInfo.setUserAccount(storeInfo.getStoreCode());
        userInfo.setPhoneNumber(storeInfo.getContactPhone());
        // 这里的用户状态和门店状态是绑定的
        userInfo.setStatus(storeInfo.getStatus());
        userInfo.setIsStoreUser(0);
        userInfo.setStoreId(storeInfo.getId());
        userInfo.setPassword(storeInfo.getContactPhone());

        // 创建用户
        userInfoRepository.createUserInfo(userInfo);

        // 保存用户权限
        // 这里去查询一下门店管理员的角色 从门店创建的默认就是门店管理员
        RoleInfo roleInfo = roleInfoRepository.selectStoreAdmin();
        userRoleRelRepository.createUserRoleRel(userInfo.getId(), CollUtil.newArrayList(roleInfo.getId()));
    }

}
